package cn.blu10ph.trustshare.service;

import cn.blu10ph.trustshare.bean.notice.GetNoticesMsg;
import cn.blu10ph.trustshare.bean.notice.TrustNotice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p> NoticeService </p >
 *
 * @author cxx
 * @date 2024/4/9 20:27
 */
@Slf4j
@Component
public class NoticeService {

    protected static final Map<String, TrustNotice> TRUST_NOTICE_STORAGE = new HashMap<>();

    protected static final MultiValueMap<String, TrustNotice> SUB_TRUST_NOTICE_STORAGE = new LinkedMultiValueMap<>();

    public void add(TrustNotice notice){
        if(!TRUST_NOTICE_STORAGE.containsKey(notice.getInfoHash())) {
            TRUST_NOTICE_STORAGE.put(notice.getInfoHash(), notice);
            SUB_TRUST_NOTICE_STORAGE.add(notice.getBaseHash(), notice);
        }
    }

    public void addAll(List<TrustNotice> notice){
        notice.forEach(this::add);
    }

    public TrustNotice get(String infoHash){
        return TRUST_NOTICE_STORAGE.get(infoHash);
    }

    public List<TrustNotice> getByBase(String baseHash){
        return SUB_TRUST_NOTICE_STORAGE.get(baseHash);
    }

    public List<TrustNotice> getAll(){
        return SUB_TRUST_NOTICE_STORAGE.values().stream().flatMap(List::stream).toList();
    }

    public List<TrustNotice> findMsg(GetNoticesMsg getNoticesMsg){
        return findMsg(null, getNoticesMsg);
    }

    public List<TrustNotice> findMsg(Set<String> nodeIds, GetNoticesMsg getNoticesMsg){
        if(StringUtils.hasText(getNoticesMsg.getInfoHash())) {
            TrustNotice notice = TRUST_NOTICE_STORAGE.get(getNoticesMsg.getInfoHash());
            if(ObjectUtils.isEmpty(notice)) {
                return Collections.emptyList();
            } else {
                return Collections.singletonList(notice);
            }
        }
        String baseHash = getNoticesMsg.getBaseHash();
        List<TrustNotice> notices = this.getByBase(baseHash);
        if(StringUtils.hasText(baseHash)) {
            notices = this.getByBase(baseHash);
        } else {
            notices = this.getAll();
        }

        if(ObjectUtils.isEmpty(notices)) {
            return Collections.emptyList();
        }

        if(!ObjectUtils.isEmpty(nodeIds)) {
            notices = notices.stream()
                    .filter(item-> nodeIds.contains(item.getFromNode()))
                    .collect(Collectors.toList());
        }

        if(StringUtils.hasText(getNoticesMsg.getFromNode())) {
            notices = notices.stream()
                    .filter(item-> getNoticesMsg.getFromNode().equals(item.getFromNode()))
                    .collect(Collectors.toList());
        }

        if(StringUtils.hasText(getNoticesMsg.getType())) {
            notices = notices.stream()
                    .filter(item-> getNoticesMsg.getType().equals(item.getType()))
                    .collect(Collectors.toList());
        }
        return notices;
    }

    public void remove(String infoHash){
        TrustNotice item = get(infoHash);
        if(ObjectUtils.isEmpty(item)){
            return;
        }
        TRUST_NOTICE_STORAGE.remove(infoHash);

        List<TrustNotice> values = getByBase(item.getBaseHash());
        if (!ObjectUtils.isEmpty(values)) {
            SUB_TRUST_NOTICE_STORAGE.remove(item.getBaseHash());
            values = values.stream()
                    .filter(temp->!item.getInfoHash().equals(temp.getInfoHash()))
                    .collect(Collectors.toList());
            SUB_TRUST_NOTICE_STORAGE.put(item.getBaseHash(), values);
        }
    }

    public void removeByBase(String baseHash){
        SUB_TRUST_NOTICE_STORAGE.remove(baseHash);
    }

}
